
#ifndef _NEBULA_SERVICE_SAMPLESERVICE_H_
#define _NEBULA_SERVICE_SAMPLESERVICE_H_

#include "Nebula.h"

#include <memory>

#include "SampleTasks.h"
#include "Utility/Thread.h"
#include "Utility/AutoLock.h"

using namespace ::nebula::sdk;
using namespace ::nebula::utility;

namespace nebula { namespace sample {

// Sample service inherit from ServiceBase
class SampleService : public ServiceBase
{
public:
	SampleService();

public:
	//service controlling functions, see details in the implementation file
	virtual unsigned int OnInitialize ();
	virtual unsigned int OnStart      ();
	virtual void         OnStop       ();
	virtual void         OnFinalize   ();

private:
	//////////////////////////////////////////////////////////////////////////	
	//Key updating: a synchronous POST interface
	//URL                  : POST "http://host:port/sample/key"
	//Slot type            : Update
	//Register  Parameters : Task Allocator, Task Processor

	//static function as a delegate to the real allocator
	static ITask* KeyUpdateTaskAlloc (IService*);
	//Task factory for creating KeyUpdateTask
	ITask*        AllocKeyUpdateTask();

	//static function as a delegate to the real processor
	static NEBULA_ERROR_CODE KeyUpdateTaskProc(IService*, IRequest*, ITask*, ITask**);
	//actual point for key update handling
	NEBULA_ERROR_CODE ProcKeyUpdateTask (IRequest*, ITask*, ITask**);

	//////////////////////////////////////////////////////////////////////////	
	//Key deleting: a synchronous DELETE interface
	//URL                  : DELETE "http://host:port/sample/key"
	//Slot type            : Delete
	//Register  Parameters : Deletion Processor

	//static function as a delegate to the real deletion member
	static NEBULA_ERROR_CODE KeyDeleteProc(IService*, IRequest*);

	//actual point for key deletion
	NEBULA_ERROR_CODE ProcKeyDelete (IRequest*);

	//member variables for key storage and lock
	std::string          _key;
	std::auto_ptr<Mutex> _key_lock;

private:
	//////////////////////////////////////////////////////////////////////////	
	//File encryption & decryption processing

	//Either the encryption or the decryption are using the same data format
	//thus the 4 interfaces share the same Task Allocator
	static ITask* FileTaskAlloc(IService*);
	ITask* AllocFileTask();

	//Thread pool type definition
	typedef TaskProcessor<SampleService> Processor;

	//File encryption interface:
	//URL                  : POST "http://host:port/sample/encrypt"
	//Slot type            : Push
	//Register  Parameters : Task Allocator, TODO-task Queue
	ITodoTaskQueue* _encrypt_in_queue;

	//URL                  : PUT "http://host:port/sample/encrypt"
	//Slot type            : Pop
	//Register  Parameters : DONE-task Queue
	IDoneTaskQueue* _encrypt_out_queue;

	//Task processor for file encryption request
	Processor _encrypt_processor;

	//Encryption routines
	//TaskProcessor routine
	NEBULA_ERROR_CODE ProcEncrpytFile(std::auto_ptr<ITask> task);
	//Real encryption flow
	NEBULA_ERROR_CODE EncryptFileTask(EncryptFile*, const std::string& key);
	

	//File decryption interface:
	//URL                  : POST "http://host:port/sample/decrypt"
	//Slot type            : Push
	//Register  Parameters : Task Allocator, TODO-task Queue
	ITodoTaskQueue* _decrypt_in_queue;

	//URL                  : PUT "http://host:port/sample/decrypt"
	//Slot type            : Pop
	//Register  Parameters : DONE-task Queue
	IDoneTaskQueue* _decrypt_out_queue;

	//Task processor for file decryption request
	Processor _decrypt_processor;

	//Decryption routines
	//TaskProcessor routine
	NEBULA_ERROR_CODE ProcDecrpytFile(std::auto_ptr<ITask> task);	
	//Real decryption flow
	NEBULA_ERROR_CODE DecryptFileTask(EncryptFile*);

	//This function is in charge of the dummy encryption & decryption algorithm
	void EncryptString(std::string& data, const std::string& key);

	//The task filter, should the "task" be transferred to "dest"?
	static bool TaskFilter(IService*, const char* dest, const ITask* task);

private:

	//////////////////////////////////////////////////////////////////////////	
	//Service Statistic Query
	//URL                  : GET "http://host:port/sample/stat"
	//Slot type            : Query
	//Register  Parameters : Request Handler

	//member variables for service statistic data storage
	std::auto_ptr<RuntimeStat> _runtime_stat;
	std::auto_ptr<Mutex>       _runtime_stat_lock;
	void TaskStatistic(EncryptFile* task);

	static NEBULA_ERROR_CODE QueryRunTimeStatProc (IService*, IRequest*, ITask**);
	NEBULA_ERROR_CODE ProcQueryRunTimeStat (IRequest*, ITask**);
	
};

} } //end of nebula::sample

#endif // end of _NEBULA_SERVICE_SAMPLESERVICE_H_
